package com.gopay.bis.manager.bank.ebank;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.BisPayCheckUtils;
import com.gopay.bis.common.util.DateUtils;
import com.gopay.bis.common.util.TransUtils;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.CcbConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ccb.ebank.pay.CcbB2cMessage;
import com.gopay.common.domain.bis.TradeCodeConstants;
import com.gopay.common.domain.user.mcc.UserMccTransformReq;
import com.gopay.common.domain.user.mcc.UserMccTransformRes;
import com.gopay.common.exception.GopayException;
import com.gopay.common.user.mcc.manager.UserMccTransformManager;
import com.gopay.common.util.JavaScriptUtil;
import com.gopay.common.util.TransUtil;
import com.gopay.remote.bank.BankManagerRemoteService;
import com.gopay.remote.bank.businesses.BankService;

/**
 * 建行支付网关B2C对象封装
 * 
 * @CcbB2cManager.java
 * @author WangHongFei
 */
public class CcbB2cManager implements BankManagerRemoteService {

    @Resource(name = "ccbB2cBankServiceClient")
    private BankService ccbB2cBankServiceClient;

    @Resource(name = "ccbB2cBankServiceClientHna")
    private BankService ccbB2cBankServiceClientHna;

    @Resource(name = "ccbConfig")
    private Map<String, String> ccbConfig;

    @Resource(name = "userMccTransformManager")
    private UserMccTransformManager userMccTransformManager;

    /**
     * B2C签名
     * 
     * @param CcbB2cMessage
     * @return CcbB2cMessage
     */
    public CcbB2cMessage sign(BaseMessage msg) throws GopayException {

        Map<String, String> corpInfo = null;

        UserMccTransformReq userM = new UserMccTransformReq();
        userM.setBankCode(BankConstants.BANK_LOGO_CCB);
        userM.setCustId(msg.getSpecial2());
        UserMccTransformRes userRes = userMccTransformManager.graspUserMccInfo(userM);

        if (userRes == null) {
            if ((BankConstants.GOPAY_CHONGZHI_CUSTID).equals(msg.getSpecial2())) {
                corpInfo = new HashMap<>();
                corpInfo.put("smerId", BankConstants.GOPAY_CODE);
                corpInfo.put("merName", BankConstants.GOPAY_NAME);
            }
        } else {
            corpInfo = new HashMap<>();
            String smerId = userRes.getProvince() + userRes.getBankMccCode() + userRes.getGopayMccNum();
            corpInfo.put("smerId", smerId);
            corpInfo.put("merName", userRes.getCorpName());
        }

        if (checkCustCorpInfoIsNew(corpInfo)) {
            return signNew(msg, corpInfo);
        } else {
            return signOld(msg);
        }
    }

    public CcbB2cMessage signOld(BaseMessage msg) throws GopayException {
        CcbB2cMessage message = (CcbB2cMessage) msg;
        // 是否信用卡充值
        String tempKeyStr = ccbConfig.get("CCB.PBLIC.KEY");
        String postId = ccbConfig.get("CCB.POSID");
        String publicKey = ccbConfig.get("CCB.PBLIC.KEY");
        // 判断是否使用小额商户
        if (msg.isSmallMer()) {
            tempKeyStr = ccbConfig.get("CCB.SMALL.PBLIC.KEY");
            postId = ccbConfig.get("CCB.SMALL.POSID");
            publicKey = ccbConfig.get("CCB.SMALL.PBLIC.KEY");
        } else {
            // 建行借贷分离判断
            if (!message.isSupportCredit()) {
                tempKeyStr = ccbConfig.get("CCB.INCHARAGE.PBLIC.KEY");
                postId = ccbConfig.get("CCB.INCHARAGE.POSID");
                publicKey = ccbConfig.get("CCB.INCHARAGE.PBLIC.KEY");
            }
        }

        tempKeyStr = tempKeyStr.substring(tempKeyStr.length() - 30, tempKeyStr.length());
        message.setPub(tempKeyStr);
        message.setPostId(postId);
        message.setPublicKey(publicKey);
        message.setTxCode(ccbConfig.get("CCB.B2C.TXCODE.PAY.P"));
        // 1- 防钓鱼接口
        message.setType("1");
        // 默认0，可不写
        message.setGateWay("W1");
        // 客户注册信息 可为空
        message.setReginfo("");
        // 商品信息 可为空
        message.setProinfo("");
        // 商户URL 可为空
        message.setReferer("");
        message.setRemark1("");
        message.setRemark2("");
        message.setClientIp("");
        message.setBankUrl(message.getPayUrl());
        message.setMerchantId(message.getMerID());
        message.setBranchId(ccbConfig.get("CCB.BRANCHID"));
        message.setCurCode(ccbConfig.get("CCB.CURCODE.RMB"));
        message.setPlainMessage(buildPlain(message));
        BankLogUtils.printB2CManagerSignSendLog(message);
        String signStr;
        if (message.isHna()) {
            signStr = (String) ccbB2cBankServiceClientHna.sign(message);
        } else {
            signStr = (String) ccbB2cBankServiceClient.sign(message);
        }
        message.setSignMessage(signStr);
        BankLogUtils.printB2CManagerSignReturnLog(message);
        return message;
    }

    public CcbB2cMessage signNew(BaseMessage msg, Map<String, String> corpInfo) throws GopayException {
        CcbB2cMessage message = (CcbB2cMessage) msg;
        // 是否信用卡充值
        String tempKeyStr = ccbConfig.get("CCB.PBLIC.KEY");
        String postId = ccbConfig.get("CCB.POSID");
        String publicKey = ccbConfig.get("CCB.PBLIC.KEY");       
        // 判断是否使用小额商户
        if (msg.isSmallMer()) {
            tempKeyStr = ccbConfig.get("CCB.SMALL.PBLIC.KEY");
            postId = ccbConfig.get("CCB.SMALL.POSID");
            publicKey = ccbConfig.get("CCB.SMALL.PBLIC.KEY");
        } else {
            // 建行借贷分离判断
            if (!message.isSupportCredit()) {
                tempKeyStr = ccbConfig.get("CCB.INCHARAGE.PBLIC.KEY");
                postId = ccbConfig.get("CCB.INCHARAGE.POSID");
                publicKey = ccbConfig.get("CCB.INCHARAGE.PBLIC.KEY");
            }
        }
        tempKeyStr = tempKeyStr.substring(tempKeyStr.length() - 30, tempKeyStr.length());
        message.setPub(tempKeyStr);
        message.setPostId(postId);
        message.setPublicKey(publicKey);
        message.setTxCode(ccbConfig.get("CCB.B2C.TXCODE.PAY.P"));
        // 1- 防钓鱼接口
        message.setType("1");
        // 默认0，可不写
        message.setGateWay("W1");
        // 客户注册信息 可为空
        message.setReginfo("");
        // 商品信息 可为空
        message.setProinfo("");
        // 商户URL 可为空
        message.setReferer("");
        message.setRemark1("");
        message.setRemark2("");
        message.setClientIp("");
        message.setBankUrl(message.getPayUrl());
        message.setMerchantId(message.getMerID());
        message.setBranchId(ccbConfig.get("CCB.BRANCHID"));
        message.setCurCode(ccbConfig.get("CCB.CURCODE.RMB"));

        // 新增字段
        // 银行前三位有105 地区码1100 MCC码 后面的4位序列号
        // 二级商户名称
        // 客户属于哪个省
        // MCC码
        // 交易类型码
        message.setSmerId(BankConstants.ACQUIRER_CODE + corpInfo.get("smerId").trim());// 二级商户代码105110073991852
        try {
            message.setSmerName(JavaScriptUtil.escape(corpInfo.get("merName") + "").trim());// 二级商户名称
        } catch (Exception e) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_000F1002,
                    "escape 编码异常-->编码内容:" + corpInfo.get("merName") + ":订单号" + msg.getOrderId(), e);
        }
        String mcc = message.getSmerId().substring(7, 11);
        message.setSmerTypeId(mcc);// 二级商户类别代码MCC
        message.setTradeCode(TradeCodeConstants.WSZF001);// 贾总要求写死的
        // 还差一个银联的交易类型
        message.setTradeName("0");
        message.setSmerType("0");
        message.setSmeProType("0");
        message.setProname("0");

        message.setPlainMessage(buildPlainNew(message));
        BankLogUtils.printB2CManagerSignSendLog(message);
        String signStr;
        if (message.isHna()) {
            signStr = (String) ccbB2cBankServiceClientHna.sign(message);
        } else {
            signStr = (String) ccbB2cBankServiceClient.sign(message);
        }
        message.setSignMessage(signStr);
        BankLogUtils.printB2CManagerSignReturnLog(message);
        return message;
    }

    private boolean checkCustCorpInfoIsNew(Map<String, String> corpInfo) throws GopayException {
        if (corpInfo == null) {
            return false;
        }
        String smerId = corpInfo.get("smerId");
        if (smerId == null || StringUtils.isBlank(smerId)) {
            return false;
        }
        return true;
    }

    /**
     * B2C验签
     * 
     * @param CcbB2cMessage
     * @return boolean
     */
    public Object verify(BaseMessage msg) throws GopayException {
        CcbB2cMessage message = (CcbB2cMessage) msg;
        StringBuffer sb = new StringBuffer("");
        if (StringUtils.isBlank(message.getAccType())) {
            sb.append("POSID=").append(message.getPostId());
            sb.append("&BRANCHID=").append(message.getBranchId());
            sb.append("&ORDERID=").append(message.getOrderId());
            sb.append("&PAYMENT=").append(message.getPayment());
            sb.append("&CURCODE=").append(message.getCurCode());
            sb.append("&REMARK1=").append(message.getRemark1());
            sb.append("&REMARK2=").append(message.getRemark2());
            sb.append("&SUCCESS=").append(message.getSuccess());
            sb.append(adjustStringNull(message.getType(), message.getReferer(), message.getClientIp()));
        } else {
            sb.append("POSID=").append(message.getPostId());
            sb.append("&BRANCHID=").append(message.getBranchId());
            sb.append("&ORDERID=").append(message.getOrderId());
            sb.append("&PAYMENT=").append(message.getPayment());
            sb.append("&CURCODE=").append(message.getCurCode());
            sb.append("&REMARK1=").append(message.getRemark1());
            sb.append("&REMARK2=").append(message.getRemark2());
            sb.append("&ACC_TYPE=").append(message.getAccType());
            sb.append("&SUCCESS=").append(message.getSuccess());
            sb.append(adjustStringNull(message.getType(), message.getReferer(), message.getClientIp()));
        }
        message.setPlainMessage(sb.toString());
        BankLogUtils.printB2CManagerVerifySendLog(message);
        boolean flag;
        if (message.isHna()) {
            flag = (Boolean) ccbB2cBankServiceClientHna.verify(message);
        } else {
            flag = (Boolean) ccbB2cBankServiceClient.verify(message);
        }
        BankLogUtils.printB2CManagerVerifyReturnLog(message, flag);
        return flag;
    }

    /**
     * B2C单笔订单查询
     * 
     * @param CcbB2cMessage
     * @return CcbB2cMessage
     */
    public CcbB2cMessage query(Object obj) throws GopayException {
        CcbB2cMessage message = (CcbB2cMessage) obj;

        if (BisPayCheckUtils.checkExternalOrderID(message.getOrderId())) {
            if (TransUtil.getCurrentDateStr().equals(DateUtils.format(message.getOrderDate(), "yyyyMMdd"))) {
                message.setKind("0"); // 0:未结算流水 1:已结算流水
            } else {
                message.setKind("1"); // 0:未结算流水 1:已结算流水
            }
            message.setOrder(message.getOrderId()); // 订单号已经换了另外字段,并且是为了按时间段查询
        }
        message.setLanguage("CN");// 语言
        message.setRequestSn(TransUtils.getPackageID());
        message.setTxCode(CcbConstants.MERCHANT_PAY_QUERY);
        message.setPage("1");

        String postId = ccbConfig.get("CCB.POSID");

        //wap订单走大额的商户号
        if (BisBankBusinessProd._11.value.equals(message.getBankBusProd().value)) {
            //默认为手机柜台号
            postId = ccbConfig.get("CCB.MOBILE.POSID");
            if (message.isSmallMer()) {
                // 判断是否使用小额商户
                postId = ccbConfig.get("CCB.SMALL.POSID");
            } 
            if(!message.isSupportCredit()){
                //判断是否借贷分离
                postId = ccbConfig.get("CCB.INCHARAGE.POSID"); 
            }
        } else if (message.isSmallMer()) {
            // 判断是否使用小额商户
            postId = ccbConfig.get("CCB.SMALL.POSID");
        } else {
            // 建行对账借贷分离判断
            if (!message.isSupportCredit()) {
                postId = ccbConfig.get("CCB.INCHARAGE.POSID");
            }
        }

        message.setPoscode(postId);
        message.setStatus("3");
        message.setStartDate(DateUtils.date2string(DateUtils.now(), "yyyyMMdd"));
        message.setEndDate(DateUtils.date2string(DateUtils.now(), "yyyyMMdd"));
        BankLogUtils.printB2CManagerQuerySendLog(message, "");
        CcbB2cMessage ccbMessage;
        if (message.isHna()) {
            ccbMessage = (CcbB2cMessage) ccbB2cBankServiceClientHna.query(message);
        } else {
            ccbMessage = (CcbB2cMessage) ccbB2cBankServiceClient.query(message);
        }
        ccbMessage.setOutStlmCd(BankConstants.BANK_LOGO_CCB); // 为了区分日志输出
        BankLogUtils.printB2CManagerQueryReturnLog(ccbMessage);
        return ccbMessage;
    }

    /**
     * 构建B2CNEW明文串
     * 
     * @param CcbB2cMessage
     * @return String
     */
    private String buildPlainNew(CcbB2cMessage message) {
        StringBuffer sb = new StringBuffer("");
        sb.append("MERCHANTID=").append(message.getMerchantId());
        sb.append("&POSID=").append(message.getPostId());
        sb.append("&BRANCHID=").append(message.getBranchId());
        sb.append("&ORDERID=").append(message.getOrderId());
        sb.append("&PAYMENT=").append(message.getAmount().toString());
        sb.append("&CURCODE=").append(message.getCurCode());
        sb.append("&TXCODE=").append(message.getTxCode());
        sb.append("&REMARK1=").append(message.getRemark1());
        sb.append("&REMARK2=").append(message.getRemark2());
        sb.append("&TYPE=").append(message.getType());
        sb.append("&PUB=").append(message.getPub());
        sb.append("&GATEWAY=").append(message.getGateWay());
        sb.append("&CLIENTIP=").append(message.getClientIp());
        sb.append("&REGINFO=").append(message.getReginfo());
        sb.append("&PROINFO=").append(message.getProinfo());
        sb.append("&REFERER=").append(message.getReferer());
        // 2015年建行新增8个字段
        sb.append("&SMERID=").append(message.getSmerId());
        sb.append("&SMERNAME=").append(message.getSmerName());
        sb.append("&SMERTYPEID=").append(message.getSmerTypeId());
        sb.append("&SMERTYPE=").append(message.getSmerType());
        sb.append("&TRADECODE=").append(message.getTradeCode());
        sb.append("&TRADENAME=").append(message.getTradeName());
        sb.append("&SMEPROTYPE=").append(message.getSmeProType());
        sb.append("&PRONAME=").append(message.getProname());
        return sb.toString();
    }

    /**
     * 构建B2C明文串
     * 
     * @param CcbB2cMessage
     * @return String
     */
    private String buildPlain(CcbB2cMessage message) {
        StringBuffer sb = new StringBuffer("");
        sb.append("MERCHANTID=").append(message.getMerchantId());
        sb.append("&POSID=").append(message.getPostId());
        sb.append("&BRANCHID=").append(message.getBranchId());
        sb.append("&ORDERID=").append(message.getOrderId());
        sb.append("&PAYMENT=").append(message.getAmount().toString());
        sb.append("&CURCODE=").append(message.getCurCode());
        sb.append("&TXCODE=").append(message.getTxCode());
        sb.append("&REMARK1=").append(message.getRemark1());
        sb.append("&REMARK2=").append(message.getRemark2());
        sb.append("&TYPE=").append(message.getType());
        sb.append("&PUB=").append(message.getPub());
        sb.append("&GATEWAY=").append(message.getGateWay());
        sb.append("&CLIENTIP=").append(message.getClientIp());
        sb.append("&REGINFO=").append(message.getReginfo());
        sb.append("&PROINFO=").append(message.getProinfo());
        sb.append("&REFERER=").append(message.getReferer());
        // 2015年建行新增8个字段
        return sb.toString();
    }

    /**
     * 防钓鱼接口如果启用了，则在返回值时做判断，如果返回的值stype为空， 则验签的时候不组装三个参数 。 这样验签也会成功
     */
    private String adjustStringNull(String sType, String sReferer, String sClientip) {
        StringBuffer sb = new StringBuffer("");
        if (StringUtils.isNotEmpty(sType)) {
            sb.append("&TYPE=" + StringUtils.trimToEmpty(sType));
            sb.append("&REFERER=" + StringUtils.trimToEmpty(sReferer));
            sb.append("&CLIENTIP=" + StringUtils.trimToEmpty(sClientip));
        }
        return sb.toString();
    }

    @Override
    public Object dayend(BaseMessage base) throws GopayException, Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Object refund(BaseMessage base) throws GopayException {
        // TODO Auto-generated method stub
        return null;
    }

}
